#include "Thread.h"
#include "Log.h"

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>

Thread::Thread(const ThreadFunc &f, const string &name)
: _started(false), _pid(0), _tid(0), _funcInThread(f), _name(name){
}

void *Thread::startRoutine(void *thread){
	Thread *t = static_cast<Thread *>(thread);
	//int ret = t->runInThread();
	t->_funcInThread();
	return NULL;
}

/*
int Thread::runInThread(){
	LOG_DEBUG_VA("Thread %s runInThread()", name().c_str());
	return 0;
}
*/

void Thread::start(){
	assert(!_started);
	_started = true;
	if(pthread_create(&_tid, NULL, startRoutine, this) != 0) {
		LOG_ERROR_VA("pthread create error.");
		_started = false;
	}
	return;
}

int Thread::join(){
	assert(_started);
	return pthread_join(_tid, NULL);
}


//TcpThread
TcpThread::TcpThread(const ThreadFunc &f, const string &name)
: Thread(f, name){
}
/*
int TcpThread::runInThread(){
	int _epfd = epoll_create(1024);
	LOG_DEBUG_VA("TcpThread create epoll fd: %d", _epfd);
	if (-1 == _epfd) {
		LOG_ERROR_VA("epoll fd create error.");
		return -1;
	}
	int ret = 0;
	_listenSock = socket(AF_INET, SOCK_STREAM, 0);
	if (_listenSock < 0) {
		LOG_ERROR_VA("listening socket open error.");
		return -1;
	}
	int optval = 1;
	ret = setsockopt(_listenSock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
	if (ret < 0) {
		LOG_ERROR_VA("set socket option error.");
		return -1;
	}
	ret = ::bind(_listenSock, (struct sockaddr *)(&_listenAddr.getAddr()), sizeof(_listenAddr.getAddr()));
	if (ret < 0) {
		LOG_ERROR_VA("bind error.");
		Socket::tcpClose(_listenSock);
		return -1;
	}
	Socket::setNonBlock(_listenSock);
//	int sockFlag = fcntl(_listenSock, F_GETFL, 0);
//	fcntl(_listenSock, F_SETFL, sockFlag | O_NONBLOCK);
	ret = listen(_listenSock, 128);
	if (ret < 0) {
		char errbuf[1024];
		strerror_r(errno, errbuf, 1023);
		LOG_ERROR_VA("listening socket error: %s", errbuf);
		Socket::tcpClose(_listenSock);
		return -1;
	}
	_eplistenevent.data.u64 = 0UL;
	_eplistenevent.data.fd = _listenSock;
	_eplistenevent.events = EPOLLIN;
	ret = Socket::tcpEpollAdd(_epfd, _listenSock, &_eplistenevent);
	if (ret < 0) {
		LOG_ERROR_VA("epoll add listen sock error.");
		Socket::tcpClose(_listenSock);
		return -1;
	}
	
	while (started()) {
		int numfd = Socket::tcpEpollWait(_epfd, _epevents, 1024, -1);
		if (numfd < 0) {
			return numfd;
		}
		for (int i = 0; i < numfd; ++i) {
			if (_epevents[i].events & EPOLLIN) {
				if(_epevents[i].data.fd == _listenSock) { //just recv data, dont care new socket, i think there is not new socket
					LOG_ERROR_VA("TcpThread epoll add listen sock!.");
				}else{
					int fd = _epevents[i].data.fd;
					char buf[16];
					int len = Socket::tcpRead(fd, buf, 16, 1000);
					if(len == 0){
						LOG_DEBUG_VA("read 0 bytes, close the fd: %d", fd);
						Socket::tcpClose(fd);
						continue;
					}
					LOG_DEBUG_VA("read %d bytes: %s", len, buf);
					//do something
					Socket::tcpWrite(fd, buf, len, 1000);
					LOG_DEBUG_VA("write %d bytes: %s", len, buf);
				}
			}else if(_epevents[i].events & EPOLLHUP) {
				LOG_ERROR_VA("fd: %d get EPOLLHUP.", _epevents[i].data.fd);
				Socket::tcpClose(_epevents[i].data.fd);
			}else if (_epevents[i].events & EPOLLERR) {
				LOG_ERROR_VA("fd: %d get EPOLLERR.", _epevents[i].data.fd);
				Socket::tcpClose(_epevents[i].data.fd);
			}else if (_epevents[i].events & EPOLLOUT) {
				LOG_ERROR_VA("fd: %d get EPOLLOUT.", _epevents[i].data.fd);
				//doWriteEvent(_epevents[i].data.fd);
			}else {
				LOG_ERROR_VA("fd: %d get something wrong.", _epevents[i].data.fd);
				Socket::tcpClose(_epevents[i].data.fd);
			}
		}
	}
	return 0;
}
*/



